﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using lighttool.NavMesh;
using System.IO;

namespace navmesh_ObjToJson
{
    public partial class Form1 : Form
    {
        navVec3 min;
        navVec3 max;
        navVec3 center;
        bool isPolygon = false;  //是否是多边形数据 （导出 服务器navmesh 只能三角形模式）

        const string _BECODE = ".becode";
        const string _OBJ = ".obj";
        const string _JSON = ".json";
        const string _NAV = ".nav";

        string fileType = "";  //加载的文件类型
        string file_o_name = ""; //不带后缀的文件名
        string file_path = "";  //文件目录路径

        List<float> vs = new List<float>();   //obj 格式顺序存储
        List<List<int>> fs = new List<List<int>>(); //obj 格式顺序存储
        

        navHandle navhandle;
        public Form1()
        {
            InitializeComponent();
            navhandle = new navHandle();
            navhandle.pictureBox1 = pictureBox1;
        }
        //按钮点击
        private void DoConvertBtn_Click(object sender, EventArgs e)
        {
            string Suffix = "";
            string dataStr = "";
            switch (fileType)
            {
                case _OBJ:
                    dataStr = ToJson(textBox1.Text);
                    Suffix = _NAV + _JSON;
                    break;
                case _JSON:
                    dataStr = ToObj(textBox1.Text);
                    Suffix = _NAV + _OBJ;
                    break;
            }
            if (Suffix == "")
            {
                MessageBox.Show("保存失败");
                return;
            }


            textBox1.Text = dataStr;
            ////保存
            string path_o = Regex.Split(file_path, @"\." )[0];
            string path = path_o + Suffix;
            savefile(dataStr, path);
            //服务器 nav数据
            if (CK_sever.Checked) {
                string Spath = path_o + _NAV + _BECODE;
                savefile(Tobecode(textBox1.Text), Spath);
            }
            MessageBox.Show("保存成功");
        }

        private void savefile(string content ,string path) {
            FileStream fs = new FileStream(path, FileMode.Create);
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(content);
            fs.Write(buffer, 0, buffer.Length);
            fs.Close();
        }
        //转到json
        private string ToJson(string str)
        {
            string result = "";
            if (vs.Count < 1 || fs.Count < 1) return result;

            //拼接
            result += "{\"v\":[\r\n";
            for (int i = 0; i < vs.Count / 3; i++)
            {
                if (i > 0) result += ",\r\n";
                result += String.Format("[{0},{1},{2}]", -vs[3 * i], vs[3 * i + 1], vs[3 * i + 2]);  //导出时 X为负
            }

            result += "\r\n],\"p\":[\r\n";
            for (int i = 0; i < fs.Count; i++)
            {
                if (i > 0) result += ",\r\n";
                result += "[";
                List<int> list = fs[i];

                for (int j = list.Count - 1; j >= 0; j--)
                {
                    if (j < list.Count - 1) result += ",";
                    result += list[j] - 1;
                }
                result += "]";
            }

            result += "\r\n]}";

            return result;
        }
        //转到obj
        private string ToObj(string str)
        {
            string result = "";
            if (vs.Count < 1 || fs.Count < 1) return result;
            //拼接
            for (int i = 0; i < vs.Count / 3; i++)
            {
                result += String.Format("v {0} {1} {2}\r\n", vs[3 * i], vs[3 * i + 1], vs[3 * i + 2]);
            }

            result += "\r\n";

            for (int i = 0; i < fs.Count; i++)
            {
                result += "f";
                List<int> tlist = fs[i];
                for (int j = 0; j < tlist.Count; j++)
                {
                    result += " " + tlist[j];
                }

                result += "\r\n";
            }

            return result;
        }
        //转到becode
        private string Tobecode(string str)
        {
            string result = "";
            if (vs.Count < 1 || fs.Count < 1) return result;
            //拼接
            double mapw = max.x + 1f;
            double maph = max.z + 1f;
            result += string.Format("{0},{1}",(uint)mapw,(uint)maph);
            result += "\r\n";
            result += "g " + Regex.Split(file_o_name, @"\.")[0];
            result += "\r\n";
            for (int i = 0; i < vs.Count / 3; i++)
            {
                result += String.Format("v {0} {1} {2}\r\n", vs[3 * i] * -1, vs[3 * i + 1], vs[3 * i + 2]);  // -x
            }
            result += "\r\n";
            for (int i = 0; i < fs.Count; i++)
            {
                result += "f";
                List<int> tlist = fs[i];
                for (int j = tlist.Count - 1; j >= 0; j--)
                {
                    result += " " + tlist[j];
                }
                result += "\r\n";
            }

            return result;
        }

       
        //计算bound
        private void calcuBound()
        {
            //找到 min  、 max 点
            min = new navVec3();
            max = new navVec3();
            center = new navVec3();
            min.x = float.MaxValue;
            min.y = float.MaxValue;
            min.z = float.MaxValue;
            max.x = float.MinValue;
            max.y = float.MinValue;
            max.z = float.MinValue;
            navVec3 temp = new navVec3();
            for (var i = 0; i < vs.Count / 3; i++)
            {
                temp.x = vs[i * 3] * -1; // -x
                temp.y = vs[i * 3 +1] ; 
                temp.z = vs[i * 3 +2];
                if (temp.x < min.x) min.x = temp.x;
                if (temp.y < min.y) min.y = temp.y;
                if (temp.z < min.z) min.z = temp.z;
                if (temp.x > max.x) max.x = temp.x;
                if (temp.y > max.y) max.y = temp.y;
                if (temp.z > max.z) max.z = temp.z;
            }

            center.x = (min.x + max.x) / 2;
            center.y = (min.y + max.y) / 2;
            center.z = (min.z + max.z) / 2;
        }

        private void selectBtn_Click(object sender, EventArgs e)
        {
            openFileDialog1.Filter = "navmesh文件|*.json;*.obj";
            //if (folderBrowserDialog1.ShowDialog() == DialogResult.OK) {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                string Fname = openFileDialog1.SafeFileName;
                if (Regex.IsMatch(Fname, @"\" + _JSON))
                {
                    fileType = _JSON;
                    BtnConvert.Text = "转成OBJ";
                }
                if (Regex.IsMatch(Fname, @"\" + _OBJ))
                {
                    fileType = _OBJ;
                    BtnConvert.Text = "转成JSON";
                }
                file_o_name = Regex.Split(Fname, @"\" + fileType)[0];

                string path = openFileDialog1.FileName;
                file_path = pathBox.Text = path;
                LoadNavmesh(path, fileType);

            }
        }
        //解析
        private void parse(string content, string file_type)
        {
            vs = new List<float>();
            fs = new List<List<int>>();
            bool isCalu = false;

            if (file_type == _OBJ)
            {   //OBJ
                string[] strs = Regex.Split(content, @"\r\n");
                for (int i = 0; i < strs.Length; i++)
                {
                    string sub = strs[i];
                    string[] values;
                    values = Regex.Split(sub, @"\ +"); //按空格拆解
                    if (values.Length < 4) continue;   //数据有问题
                    switch (sub[0])
                    {
                        case 'v':
                            vs.Add(float.Parse(values[1]));
                            vs.Add(float.Parse(values[2]));
                            vs.Add(float.Parse(values[3]));
                            break;
                        case 'f':
                            List<int> list = new List<int>();
                            for (int j = 1; j < values.Length; j++)
                            {
                                try
                                {
                                    list.Add(int.Parse(values[j]));  //数值可能有问题
                                }
                                catch (Exception)
                                {
                                }
                            }
                            fs.Add(list);
                            break;
                    }
                }
                isCalu = true;
            }

            if (file_type == _JSON)
            {    //JSON
                MyJson.IJsonNode j;
                try
                {
                    j = MyJson.Parse(content);
                }
                catch (Exception)
                {
                    throw;
                }
                if (j == null) return;

                foreach (var json in j.asDict()["v"].AsList())
                {
                    vs.Add((float)json.AsList()[0].AsDouble() * -1);  //obj  -x 
                    vs.Add((float)json.AsList()[1].AsDouble());
                    vs.Add((float)json.AsList()[2].AsDouble());
                }
                foreach (var json in j.asDict()["p"].AsList())
                {
                    List<int> tlist = new List<int>();
                    IList<MyJson.IJsonNode> jlist = json.AsList();
                    for (int i = jlist.Count - 1; i >= 0; i--)
                    {
                        tlist.Add(jlist[i].AsInt() + 1);  //obj 逆向、索引+1
                    }
                    fs.Add(tlist);
                }
                isCalu = true;
            }

            if (isCalu) {
                calcuBound();  //计算aabb包围盒
                isPolygon = false;
                foreach (var item in fs)   //检查数据是否是多边形
                {
                    if (item.Count >3) {
                        isPolygon = true;
                        break;
                    }
                }
            }
        }

        //加载 navmesh
        private void LoadNavmesh(string path, string File_type)
        {
            //加载
            FileStream fst = new FileStream(path, FileMode.Open);
            int fsLen = (int)fst.Length;
            byte[] buffer = new byte[fsLen];
            fst.Read(buffer, 0, buffer.Length);
            string myStr = System.Text.Encoding.UTF8.GetString(buffer);
            textBox1.Text = myStr;
            parse(myStr, fileType);
            navhandle.Form1_Load(vs,fs);

            CK_sever.Enabled = !isPolygon;  //导出服务器nav数据 只能是三角形

            fst.Close();


        }


        private void openFileDialog1_FileOk_1(object sender, CancelEventArgs e)
        {
            BtnConvert.Enabled = true;
        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            navhandle.pictureBox1_Paint(sender, e);
        }

        private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
        {
            navhandle.pictureBox1_MouseClick(sender,e);
        }

        
    }
}
